from qtorch.core.interfaces import IRiskManager
import logging
import numpy as np
import pandas as pd
from typing import Dict, List, Any, Optional, Union
from datetime import datetime, timedelta

class RiskManager(IRiskManager):
    """增强版风险控制管理实现类"""
    
    def __init__(self,
                 max_position: float = 0.1,       # 最大持仓比例
                 max_loss: float = 0.05,          # 最大亏损比例
                 max_drawdown: float = 0.2,       # 最大回撤限制
                 volatility_limit: float = 0.03,  # 波动率限制
                 correlation_threshold: float = 0.7, # 相关性阈值
                 max_concentration: float = 0.3,  # 最大行业集中度
                 max_leverage: float = 1.5):      # 最大杠杆率
        
        self.max_position = max_position
        self.max_loss = max_loss
        self.max_drawdown = max_drawdown
        self.volatility_limit = volatility_limit
        self.correlation_threshold = correlation_threshold
        self.max_concentration = max_concentration
        self.max_leverage = max_leverage
        
        # 历史数据
        self.positions_history = []
        self.equity_curve = []
        self.daily_returns = []
        self.current_drawdown = 0.0
        self.peak_equity = 1.0
        self.current_equity = 1.0
        self.position_data = {}
        self.sector_exposure = {}
        
        # 日志
        self.logger = logging.getLogger(__name__)
        self.logger.info("增强版风险管理模块初始化完成")
        
    def validate_signals(self, signals) -> bool:
        """验证交易信号"""
        try:
            # 1. 检查持仓限制
            if not self._check_position_limit(signals):
                return False
                
            # 2. 检查亏损限制
            if not self._check_loss_limit(signals):
                return False
                
            # 3. 检查回撤限制
            if not self._check_drawdown_limit():
                return False
                
            # 4. 检查波动率限制
            if not self._check_volatility_limit(signals):
                return False
                
            # 5. 检查相关性限制
            if not self._check_correlation_limit(signals):
                return False
                
            # 6. 检查行业集中度
            if not self._check_sector_concentration(signals):
                return False
                
            # 7. 检查杠杆率
            if not self._check_leverage_limit(signals):
                return False
                
            return True
        except Exception as e:
            self.logger.error(f"风险验证失败: {str(e)}", exc_info=True)
            return False
            
    def _check_position_limit(self, signals) -> bool:
        """检查持仓限制"""
        if len(signals) > self.max_position * 100:  # 假设最大持仓数量为百分比乘以100
            self.logger.warning(f"持仓超过限制：当前{len(signals)}/最大{self.max_position*100}")
            return False
        return True
        
    def _check_loss_limit(self, signals) -> bool:
        """检查亏损限制"""
        # 计算当前亏损
        current_loss = 0.0
        for symbol, position in self.position_data.items():
            if position.get('unrealized_pnl', 0) < 0:
                current_loss += abs(position['unrealized_pnl'])
                
        # 计算新信号可能带来的亏损
        estimated_new_loss = 0.0
        # 这里应该有更复杂的估算逻辑
        
        total_loss = current_loss + estimated_new_loss
        if total_loss > self.max_loss * self.current_equity:
            self.logger.warning(f"亏损超过限制：当前{total_loss:.2%}/最大{self.max_loss:.2%}")
            return False
        return True
        
    def _check_drawdown_limit(self) -> bool:
        """检查回撤限制"""
        if self.current_drawdown > self.max_drawdown:
            self.logger.warning(f"回撤超过限制：当前{self.current_drawdown:.2%}/最大{self.max_drawdown:.2%}")
            return False
        return True
        
    def _check_volatility_limit(self, signals) -> bool:
        """检查波动率限制"""
        if len(self.daily_returns) < 20:  # 需要足够的历史数据
            return True
            
        # 计算历史波动率
        volatility = np.std(self.daily_returns[-20:]) * np.sqrt(252)  # 年化波动率
        if volatility > self.volatility_limit:
            self.logger.warning(f"波动率超过限制：当前{volatility:.2%}/最大{self.volatility_limit:.2%}")
            return False
        return True
        
    def _check_correlation_limit(self, signals) -> bool:
        """检查相关性限制"""
        # 这里应该实现相关性检查逻辑
        # 简化实现，实际应该计算持仓之间的相关性
        return True
        
    def _check_sector_concentration(self, signals) -> bool:
        """检查行业集中度"""
        # 计算行业集中度
        for sector, exposure in self.sector_exposure.items():
            if exposure > self.max_concentration:
                self.logger.warning(f"行业集中度超过限制：{sector}当前{exposure:.2%}/最大{self.max_concentration:.2%}")
                return False
        return True
        
    def _check_leverage_limit(self, signals) -> bool:
        """检查杠杆率"""
        # 计算当前杠杆率
        total_position_value = sum(pos.get('value', 0) for pos in self.position_data.values())
        current_leverage = total_position_value / self.current_equity if self.current_equity > 0 else 0
        
        # 估算新信号带来的杠杆变化
        estimated_new_leverage = current_leverage  # 简化实现
        
        if estimated_new_leverage > self.max_leverage:
            self.logger.warning(f"杠杆率超过限制：当前{estimated_new_leverage:.2f}/最大{self.max_leverage:.2f}")
            return False
        return True

    def update_risk_params(self, max_position: Optional[float] = None, max_loss: Optional[float] = None) -> None:
        """更新风险控制参数（接口兼容方法）"""
        # 调用内部方法实现参数更新
        self._update_risk_params_internal(
            max_position=max_position,
            max_loss=max_loss
        )
    
    def _update_risk_params_internal(self, max_position: Optional[float] = None, max_loss: Optional[float] = None,
                           max_dd: Optional[float] = None, volatility_limit: Optional[float] = None,
                           correlation_threshold: Optional[float] = None, max_concentration: Optional[float] = None,
                           max_leverage: Optional[float] = None) -> None:
        """内部更新风险参数的实现"""
        if max_position is not None:
            self.max_position = max_position
        if max_loss is not None:
            self.max_loss = max_loss
        if max_dd is not None:
            self.max_drawdown = max_dd
        if volatility_limit is not None:
            self.volatility_limit = volatility_limit
        if correlation_threshold is not None:
            self.correlation_threshold = correlation_threshold
        if max_concentration is not None:
            self.max_concentration = max_concentration
        if max_leverage is not None:
            self.max_leverage = max_leverage
            
        self.logger.info(f"更新风险参数: 最大持仓{self.max_position} 最大亏损{self.max_loss} "
                        f"最大回撤{self.max_drawdown} 波动率限制{self.volatility_limit}")
    
    def adjust_parameters(self, max_position: Optional[float] = None, max_loss: Optional[float] = None,
                         max_dd: Optional[float] = None, volatility_limit: Optional[float] = None,
                         correlation_threshold: Optional[float] = None, max_concentration: Optional[float] = None,
                         max_leverage: Optional[float] = None) -> None:
        """调整风险参数（统一使用max_dd替代max_drawdown）"""
        self._update_risk_params_internal(
            max_position=max_position,
            max_loss=max_loss,
            max_dd=max_dd,
            volatility_limit=volatility_limit,
            correlation_threshold=correlation_threshold,
            max_concentration=max_concentration,
            max_leverage=max_leverage
        )
        
    def apply_dynamic_parameters(self, market_state: str = "normal",
                               volatility_factor: float = 1.0,
                               risk_level: str = "medium") -> None:
        """
        动态调整风险参数，根据市场状态和波动率因子自动调整风险控制参数
        
        参数:
            market_state: 市场状态，可选值: "normal"(正常), "volatile"(波动), "crisis"(危机)
            volatility_factor: 波动率因子，大于1表示波动率增加，小于1表示波动率减少
            risk_level: 风险等级，可选值: "low"(低风险), "medium"(中等风险), "high"(高风险)
        """
        # 基础参数调整系数
        position_factor = 1.0
        loss_factor = 1.0
        dd_factor = 1.0
        
        # 根据市场状态调整
        if market_state == "volatile":
            position_factor *= 0.8
            loss_factor *= 0.9
            dd_factor *= 0.9
        elif market_state == "crisis":
            position_factor *= 0.5
            loss_factor *= 0.7
            dd_factor *= 0.6
            
        # 根据风险等级调整
        if risk_level == "low":
            position_factor *= 0.7
            loss_factor *= 0.7
            dd_factor *= 0.7
        elif risk_level == "high":
            position_factor *= 1.3
            loss_factor *= 1.2
            dd_factor *= 1.2
            
        # 应用波动率因子
        position_factor /= volatility_factor
        loss_factor /= volatility_factor
        dd_factor /= volatility_factor
        
        # 计算新的参数值
        new_max_position = self.max_position * position_factor
        new_max_loss = self.max_loss * loss_factor
        new_max_dd = self.max_drawdown * dd_factor
        new_volatility_limit = self.volatility_limit * volatility_factor
        
        # 应用新参数
        self._update_risk_params_internal(
            max_position=new_max_position,
            max_loss=new_max_loss,
            max_dd=new_max_dd,
            volatility_limit=new_volatility_limit
        )
        
        self.logger.info(f"动态调整风险参数: 市场状态={market_state}, 波动率因子={volatility_factor:.2f}, 风险等级={risk_level}")
    
    def update_account_status(self, equity: float, positions: Dict[str, Any],
                              daily_return: Optional[float] = None, sector_data: Optional[Dict[str, float]] = None) -> None:
        """更新账户状态"""
        # 更新权益曲线
        self.current_equity = equity
        self.equity_curve.append(equity)
        
        # 更新回撤
        if equity > self.peak_equity:
            self.peak_equity = equity
        
        if self.peak_equity > 0:
            self.current_drawdown = (self.peak_equity - equity) / self.peak_equity
        
        # 更新日收益率
        if daily_return is not None:
            self.daily_returns.append(daily_return)
        
        # 更新持仓数据
        self.position_data = positions
        
        # 更新行业暴露
        if sector_data:
            self.sector_exposure = sector_data
            
        self.logger.debug(f"账户状态更新: 权益{equity:.2f} 回撤{self.current_drawdown:.2%}")
    
    def get_risk_report(self) -> Dict[str, Any]:
        """获取风险报告"""
        report = {
            "current_equity": self.current_equity,
            "peak_equity": self.peak_equity,
            "current_drawdown": self.current_drawdown,
            "position_count": len(self.position_data),
            "sector_exposure": self.sector_exposure
        }
        
        # 计算波动率
        if len(self.daily_returns) >= 20:
            report["volatility_20d"] = np.std(self.daily_returns[-20:]) * np.sqrt(252)
        
        # 计算夏普比率
        if len(self.daily_returns) >= 60:
            returns_60d = self.daily_returns[-60:]
            avg_return = np.mean(returns_60d) * 252
            volatility = np.std(returns_60d) * np.sqrt(252)
            if volatility > 0:
                report["sharpe_ratio_60d"] = avg_return / volatility
        
        return report